package com.wiscamp.ninechapters.panels.application.services;

import com.wiscamp.ninechapters.panels.application.assemblers.GroupAssembler;
import com.wiscamp.ninechapters.panels.application.assemblers.RoleAssembler;
import com.wiscamp.ninechapters.panels.application.assemblers.UserAssembler;
import com.wiscamp.ninechapters.panels.application.command.BindUnbindGroupRoleCommand;
import com.wiscamp.ninechapters.panels.application.command.BindUnbindGroupUserCommand;
import com.wiscamp.ninechapters.panels.application.command.CreateGroupCommand;
import com.wiscamp.ninechapters.panels.application.command.UpdateGroupCommand;
import com.wiscamp.ninechapters.panels.application.vo.GroupVO;
import com.wiscamp.ninechapters.panels.application.vo.RoleVO;
import com.wiscamp.ninechapters.panels.application.vo.UserVO;
import com.wiscamp.ninechapters.panels.domain.repositories.GroupRepository;
import com.wiscamp.ninechapters.panels.domain.services.GroupService;
import cube.ddd.application.BaseAppService;
import cube.ddd.application.command.DeleteCommand;
import cube.ddd.application.command.DisableCommand;
import cube.ddd.application.command.EnableCommand;
import cube.ddd.aspect.HandleServiceException;
import cube.ddd.common.query.PagedObjects;
import cube.ddd.common.query.PagedQuery;
import cube.ddd.utils.AppServiceUtils;
import jakarta.validation.Valid;
import org.springframework.stereotype.Service;

import java.util.Collection;

@Service
public class GroupAppService extends BaseAppService {

    private final GroupRepository groupRepository;

    private final GroupService groupService;

    public GroupAppService(GroupRepository groupRepository, GroupService groupService) {
        this.groupRepository = groupRepository;
        this.groupService = groupService;
    }

    @HandleServiceException
    public GroupVO getGroup(long groupId) {
        return AppServiceUtils.getById(groupId, groupService::getGroup,
                GroupAssembler.Instance::toGroupVO);
    }

    @HandleServiceException
    public GroupVO getGroupByCode(long appId, String groupCode) {
        return AppServiceUtils.getByIdAndText(appId, groupCode, groupRepository::getGroupByCode,
                GroupAssembler.Instance::toGroupVO);
    }

    @HandleServiceException
    public Collection<GroupVO> getGroupsByName(long appId, String groupName) {
        return AppServiceUtils.getListByIdAndText(appId, groupName, groupRepository::getGroupsByName,
                GroupAssembler.Instance::toGroupVO);
    }

    @HandleServiceException
    public PagedObjects<GroupVO> getGroupsByQuery(PagedQuery pagedQuery) {
        var pagedObjects = groupRepository.getGroupsByQuery(pagedQuery);
        return AppServiceUtils.convertPagedObjects(pagedObjects, GroupAssembler.Instance::toGroupVO);
    }

    @HandleServiceException
    public Collection<UserVO> getUsersByGroup(long groupId) {
        return AppServiceUtils.getListById(groupId, groupService::getUsersByGroup,
                UserAssembler.Instance::toUserVO);
    }

    @HandleServiceException
    public Collection<RoleVO> getRolesByGroup(long groupId) {
        return AppServiceUtils.getListById(groupId, groupService::getRolesByGroup,
                RoleAssembler.Instance::toRoleVO);
    }

    @HandleServiceException
    public GroupVO createGroup(@Valid CreateGroupCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), groupService::createGroup,
                GroupAssembler.Instance::toGroupVO, GroupAssembler.Instance::fromCreateCommand);
    }

    @HandleServiceException
    public GroupVO updateGroup(@Valid UpdateGroupCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.createOrUpdateBy(command, command.getOperatorId(), groupService::updateGroup,
                GroupAssembler.Instance::toGroupVO, GroupAssembler.Instance::fromUpdateCommand);
    }

    @HandleServiceException
    public boolean deleteGroup(@Valid DeleteCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.delete(command.getId(), command.getOperatorId(), groupService::deleteGroup);
    }

    @HandleServiceException
    public boolean enableGroup(@Valid EnableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.enable(command.getId(), command.getOperatorId(), groupService::enableGroup);
    }

    @HandleServiceException
    public boolean disableGroup(@Valid DisableCommand command) {
        command.setOperatorId(getCurrentUserId());
        return AppServiceUtils.disable(command.getId(), command.getOperatorId(), groupService::disableGroup);
    }


    @HandleServiceException
    public boolean bindGroupRole(@Valid BindUnbindGroupRoleCommand command) {
        command.setOperatorId(getCurrentUserId());
        return groupService.bindGroupRole(command.getGroupId(), command.getRoleId());
    }

    @HandleServiceException
    public boolean unbindGroupRole(@Valid BindUnbindGroupRoleCommand command) {
        command.setOperatorId(getCurrentUserId());
        return groupService.unbindGroupRole(command.getGroupId(), command.getRoleId());
    }

    @HandleServiceException
    public boolean bindGroupUser(@Valid BindUnbindGroupUserCommand command) {
        command.setOperatorId(getCurrentUserId());
        return groupService.bindGroupUser(command.getGroupId(), command.getUserId());
    }

    @HandleServiceException
    public boolean unbindGroupUser(@Valid BindUnbindGroupUserCommand command) {
        command.setOperatorId(getCurrentUserId());
        return groupService.unbindGroupUser(command.getGroupId(), command.getUserId());
    }
}
